package com.doucat.support.thread;

import android.util.Log;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * -----------------------------------------------------------------
 * Copyright (C) 2021-2031, by tonly, All rights reserved.
 * -----------------------------------------------------------------
 * File: WorkersThread.java
 * Author: wangfy
 * Create: 2021/7/10 09:45
 */
public class WorkersThread {
    private String TAG="WorkersThread";
    private static class Holder{
        static WorkersThread instance=new WorkersThread();
    }
    public static WorkersThread getInstance() {
        return WorkersThread.Holder.instance;
    }

    private ThreadPool threadPool;

    /**
     * 一般说来，大家认为线程池的大小经验值应该这样设置：（其中N为CPU的核数）
     * 如果是CPU密集型应用，则线程池大小设置为N+1
     * 如果是IO密集型应用，则线程池大小设置为2N+1
     *
     * I/O密集型
     * I/O bound 指的是系统的CPU效能相对硬盘/内存的效能要好很多，此时，系统运作，大部分的状况是 CPU 在等 I/O (硬盘/内存) 的读/写，此时 CPU Loading 不高。
     * CPU-bound
     * CPU bound 指的是系统的 硬盘/内存 效能 相对 CPU 的效能 要好很多，此时，系统运作，大部分的状况是 CPU Loading 100%，CPU 要读/写 I/O (硬盘/内存)，I/O在很短的时间就可以完成，而 CPU 还有许多运算要处理，CPU Loading 很高。
     *
     * Android 应用的话应该是属于IO密集型应用，所以数量一般设置为 2N+1
     */
    private WorkersThread() {
        int CPU_COUNT = Runtime.getRuntime().availableProcessors();
        int corePoolSize=Math.max(2, Math.min(CPU_COUNT - 1, 4));
        int maximumPoolSize=CPU_COUNT * 2 + 1;

        Log.v(TAG,"CPU_COUNT="+CPU_COUNT);
        Log.v(TAG,"corePoolSize="+corePoolSize);
        Log.v(TAG,"maximumPoolSize="+maximumPoolSize);
        threadPool= new ThreadPool.Build()
                .setAllowCoreThreadTimeOut(false)
                .setKeepAliveTime(30)
                .setUnit(TimeUnit.SECONDS)
                //没达到corePoolSize时直接执行，达到后先进WorkQueue，WorkQueue满后，若未到maximumPoolSize，启动线程执行
                .setCorePoolSize(corePoolSize)
                //达到max后提交任务会调用RejectedExecutionHandler，保证最大运行的线程数量
                //maximumPoolSize为int max时，不会执行RejectedExecutionHandler拒绝任务
                .setMaximumPoolSize(maximumPoolSize)
                .setWorkQueue(new SynchronousQueue<>())
                .setThreadFactory(Executors.defaultThreadFactory())
                .setHandler(new RejectedExecutionHandler() {
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        Log.v(TAG,"runOnThread:"+"被拒绝");
                    }
                })
                .create();
    }
    public void execute(Runnable runnable) {
        threadPool.execute(runnable);
    }

    /**
     * app各个界面都用这个线程池，不要干掉
     */
    public void shutdownNow() {
//        threadPool.shutdownNow();
    }

}